package com.wtwd.campus.jdzc.controller;

import com.alibaba.fastjson.JSONObject;
import com.wtwd.campus.jdzc.common.Constant;
import com.wtwd.campus.jdzc.common.RespCode;
import com.wtwd.campus.jdzc.common.RespEntity;
import com.wtwd.campus.jdzc.entity.DeviceInfo;
import com.wtwd.campus.jdzc.entity.JdzcUser;
import com.wtwd.campus.jdzc.entity.vo.LoginVo;
import com.wtwd.campus.jdzc.service.AuthService;
import com.wtwd.campus.jdzc.service.JdzcDeviceInfoService;
import com.wtwd.campus.jdzc.service.JdzcService;
import com.wtwd.campus.jdzc.service.JdzcStudentService;
import com.wtwd.campus.service.RedisService;
import com.wtwd.campus.utils.CommandSendUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author: ldaoliang
 * @DateTime: 2022/2/14 13:59
 * @Description: 给该客户提供与沃特校园微信公众号一样的功能的API接口。考虑到耦合性的问题，不直接使用原controller。复制出一份接口让客户对接使用
 * 1、用户模块（发送验证码功能、小程序推送、微信扫码功能沃特API不提供）
 * 2、查询数据时需要确定是否为对应的组织（A01A45A01）
 */
@RestController
@RequestMapping("/jdzc/user")
public class JdzcUserController {

    private static final Logger logger = LoggerFactory.getLogger(JdzcUserController.class);


    @Autowired
    private JdzcService jdService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private AuthService authService;

    @Autowired
    private JdzcStudentService jdzcStudentService;

    @Autowired
    private JdzcDeviceInfoService jdDeviceInfoService;

    @Autowired
    private CommandSendUtils commandSendUtils;


    /**
     * 登录
     * phone String 手机号
     * type  Integer 客户端类型
     *
     * @param jsonObject
     * @return
     */
    @PostMapping("/login")
    public RespEntity login(@RequestBody JSONObject jsonObject) {
        logger.info("login phone ={} ", jsonObject);
        String phone = jsonObject.getString("phone");
        Integer type = jsonObject.getInteger("type");
        if (StringUtils.isBlank(phone) || type == null) {
            return new RespEntity(RespCode.PARAMS_ERROR);
        }
        JdzcUser userInfo = jdService.getUserInfoByPhone(phone);
        if (userInfo == null) {//储存用户信息
            userInfo = jdService.createUser(phone);
        } else {
            jdService.updateWxUserLastLoginTime(userInfo.getUserId(), new Date().getTime());
        }
        String token = jdService.createLoginToken(userInfo.getUserId());
        //鉴别用户类型
        if (type.equals(Constant.TEACHER_TYPE)) {//教师类型需要鉴别
            Boolean rest = authService.authTeacher(phone, Constant.jdzcOrgCode);
            if (!rest) {
                return new RespEntity(RespCode.USER_TEACHER_TYPE_FAILED);
            }
        }
        //角色类型存储于redis
        redisService.setKey(Constant.XCX_JDZC_USER_TYPE + phone, String.valueOf(type), 15, TimeUnit.DAYS);
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        return new RespEntity(RespCode.SUCCESS, loginVo);
    }

    /**
     * 获取绑定学生列表
     *
     * @param request
     * @return
     */
    @GetMapping("/getBindingStudents")
    public RespEntity getBindingStudents(HttpServletRequest request) {
        String token = request.getHeader(Constant.HEADER_TOKEN_KEY);
        String redisUserId = redisService.getValue(token);
        if (StringUtils.isBlank(redisUserId)) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        Integer userId = Integer.parseInt(redisUserId);
        logger.info("bindingList : userId = {}", userId);
        List<Map<String, Object>> studentList = jdService.getUserStudentList(userId);
        return new RespEntity(RespCode.SUCCESS, studentList);
    }

    /**
     * 绑定学生
     *
     * @param jsonObject
     * @return
     */
    @PostMapping("/bindingStudent")
    public RespEntity bindingStudent(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        String token = request.getHeader(Constant.HEADER_TOKEN_KEY);
        String redisUserId = redisService.getValue(token);
        if (StringUtils.isBlank(redisUserId)) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        Integer userId = Integer.parseInt(redisUserId);
        logger.info("bindingStudent : userId = {}, param = {}", userId, jsonObject);
        String imei = jsonObject.getString("imei");
        String name = jsonObject.getString("name");
        String stuNo = jsonObject.getString("stuNo");
        //先校验学生是否录入平台
        List<Map<String, Object>> stuList = jdzcStudentService.getStuByNameAndStuNo(name, stuNo);
        //校验设备是否存在
        DeviceInfo deviceInfo = jdDeviceInfoService.getDeviceInfoByImei(imei);
        if (deviceInfo == null) {
            return new RespEntity(RespCode.DEVICE_NOT_EXIST);
        }
        //校验设备是否在这个组织下
        Boolean rest = authService.authDevice(deviceInfo, Constant.jdzcOrgCode);
        if (!rest) {
            return new RespEntity(RespCode.DEVICE_NOT_BELONG_TO);
        }
        //筛选一个最有可能的学生id,同时校验了学生有没有被其他设备绑定
        /* Integer stuId = (Integer)stuList.get(0).get("student_id");*/
        Integer stuId = selectStudentId(stuList, imei, deviceInfo.getOrgCode());
        if (stuId == 0) {
            return new RespEntity(RespCode.STUDENT_DEVICE_NOT_MATCH);
        }
        //校验学生是否在该组织下
        Boolean authStudent = authService.authStudentOrgCode(stuId, Constant.jdzcOrgCode, userId);
        if (!authStudent) {
            return new RespEntity(RespCode.STUDENT_MSG_ERROR);
        }
        //进行绑定校验,判断平台是否录入设备
        boolean flag = false;
        //设备已经导入平台，判断设备的类型
        if (deviceInfo.getDeviceType() != Constant.PLATFORM_DEVICE) {
            return new RespEntity(RespCode.DEVICE_NOT_BELONG_PLATFORM);
        }
        //校验设备是否已经绑定了学生
        if (deviceInfo.getStudentId() == null) {
/*            //校验设备组织是否在学校组织之下
            String deviceOrg = deviceInfo.getOrgCode();*/
            //将设备和学生进行绑定，并且允许用户绑定
            deviceInfo.setStudentId(stuId);
            int i = jdDeviceInfoService.updateDeviceInfo(deviceInfo);
            if (i > 0) {
                flag = true;
            }
        } else if (deviceInfo.getStudentId().equals(stuId)) {
            //允许绑定
            flag = true;
        } else {
            //设备信息与学生信息不匹配
            return new RespEntity(RespCode.STUDENT_DEVICE_NOT_MATCH);
        }
        if (flag) {
            return jdService.bindingStudent(userId, imei, name, stuNo);
        }
        return new RespEntity(RespCode.FAILED);
    }

    /**
     * 解绑学生
     *
     * @return
     */
    @DeleteMapping("/unbindStudent/{studentId}")
    public RespEntity unbindStudent(@PathVariable("studentId") Integer studentId, HttpServletRequest request) {
        String token = request.getHeader(Constant.HEADER_TOKEN_KEY);
        String redisUserId = redisService.getValue(token);
        if (StringUtils.isBlank(redisUserId)) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        Integer userId = Integer.parseInt(redisUserId);
        logger.info("unbindingStudent : userId = {}, studentId = {}", userId, studentId);
        //是否可以解绑
        boolean flag = false;
        //用于判断可以解绑时，该家长是否是管理员
        boolean isMan = false;
        //鉴别学生是否属于该组织下的学生
        Boolean rest = authService.authStudent(studentId, Constant.jdzcOrgCode, userId);
        if (!rest) {
            return new RespEntity(RespCode.STUDENT_MSG_ERROR);
        }
        //获取该学生的绑定家长列表
        List<Map<String, Object>> phoneList = jdzcStudentService.bindStudentPhoneList(studentId);
        if (phoneList == null || phoneList.size() == 0) {
            return new RespEntity(RespCode.STUDENT_NO_BANDING_PARENTS);
        }
        if (phoneList.size() == 1) {
            //当仅有一个绑定家长时，可以直接操作
            flag = true;
            isMan = true;
        } else {
            //首先判断是否是管理员
            for (Map<String, Object> map : phoneList) {
                Integer wxUserId = (Integer) map.get("user_id");
                Integer isManager = (Integer) map.get("is_manager");
                if (wxUserId.equals(userId)) {
                    flag = (isManager == 1 ? false : true);
                }
            }
        }
        if (flag) {
            //进行解绑操作
            jdzcStudentService.updateStudentWxUserBindStatus(0, studentId);
            int i = jdzcStudentService.unbindStudent(userId, studentId);
            //如果是管理员，得将学生和设备进行解绑
            if (isMan) {
                //如果是喜马拉雅的设备，还需给设备发送绑定关系
                DeviceInfo deviceInfo = jdDeviceInfoService.getDeviceInfoByStuId(studentId);
                if (deviceInfo != null && !StringUtils.isBlank(deviceInfo.getOrgCode())) {
                    if (deviceInfo.getOrgCode().contains("A01A03A05")) {
                        // 下发绑定关系指令
                        //设备在线则进行发送
                        //根据学生id获取年级、班级、学生名称、学校名称
                        Map<String, Object> bindingMap = new HashMap<>();
                        bindingMap.put("imei", deviceInfo.getImei());
                        bindingMap.put("status", Constant.DEVICE_UNBINDING);
                        bindingMap.put("commandNumber", getCurTime());
                        bindingMap.put("schoolName", "");
                        bindingMap.put("classesName", "");
                        bindingMap.put("studentName", "");
                        bindingMap.put("gradeName", "");
                        String s = JSONObject.toJSONString(bindingMap);
                        boolean isOnline = deviceOnline(deviceInfo.getImei());
                        //进行指令下发
                        commandSendUtils.sendBindingStatus(JSONObject.parseObject(s), Constant.WX_COMMAND_USER_ID, isOnline, false);
                    }
                }
                int i1 = jdDeviceInfoService.unBindingStudentWithDevice(studentId);
            }
            return new RespEntity(i > 0 ? RespCode.SUCCESS : RespCode.FAILED);
        } else {
            return new RespEntity(RespCode.FIRST_REMOVE_MANAGER);
        }
    }

    /**
     * 绑定学生的号码列表
     *
     * @param studentId
     * @param request
     * @return
     */
    @GetMapping("/getBindStudentPhoneList/{studentId}")
    public RespEntity bindStudentPhoneList(@PathVariable("studentId") Integer studentId, HttpServletRequest request) {
        String token = request.getHeader(Constant.HEADER_TOKEN_KEY);
        String redisUserId = redisService.getValue(token);
        if (StringUtils.isBlank(redisUserId)) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        Integer userId = Integer.parseInt(redisUserId);
        //鉴别该用户是否有权获该学生的列表
        Boolean authStudent = authService.authStudent(studentId, Constant.jdzcOrgCode, userId);
        if (!authStudent){
            return new RespEntity(RespCode.STUDENT_MSG_ERROR);
        }
        logger.info("getBindPhoneList : userId = {},studentId = {}" + userId, studentId);
        List<Map<String, Object>> phoneList = jdzcStudentService.bindStudentPhoneList(studentId);
        // 防止openId未绑定号码导致查询的List中phone有null元素
        Iterator iterator = phoneList.iterator();
        Map<String, Object> firstMap = new HashMap<>();
        boolean ifMan = false;
        for (Map<String, Object> map : phoneList) {
            Integer isMan = (Integer) map.get("is_manager");
            Integer wx_user_id = (Integer) map.get("user_id");
            if (wx_user_id.equals(userId) && isMan == 1) {
                ifMan = true;
            }
            if (isMan == 1) {
                firstMap = map;
            }
        }
        while (iterator.hasNext()) {
            Map<String, Object> map = (Map<String, Object>) iterator.next();
            String phone = (String) map.get("phone");
            if (StringUtils.isBlank(phone)) {
                iterator.remove();
            }
        }
        Integer needShow = ifMan ? 1 : 0;
        List<Map<String, Object>> resultList = new ArrayList<>();
        firstMap.put("need_show", needShow);
        resultList.add(0, firstMap);
        for (Map<String, Object> map : phoneList) {
            Integer wx_user_id = (Integer) map.get("user_id");
            Integer wx_user_id2 = (Integer) firstMap.get("user_id");
            if (wx_user_id != wx_user_id2) {
                map.put("need_show", needShow);
                resultList.add(map);
            }
        }
        return new RespEntity(RespCode.SUCCESS, resultList);
    }

    /**
     * 转让管理员
     *
     * @param jsonObject
     * @return
     */
    @PostMapping("/transferManager")
    public RespEntity transferManager(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        String token = request.getHeader(Constant.HEADER_TOKEN_KEY);
        String redisUserId = redisService.getValue(token);
        if (StringUtils.isBlank(redisUserId)) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        Integer userId = Integer.parseInt(redisUserId);
        Integer id = jsonObject.getInteger("id");
        if (id==null){
            return new RespEntity(RespCode.PARAMS_ERROR);
        }
        logger.info("transferManager : id = {}" + id.toString());
        //根据id查找到绑定记录
        Map<String, Object> map = jdService.getBindingById(id);
        Integer wx_user = (Integer) map.get("user_id");
        Integer stuId = (Integer) map.get("student");
        if (wx_user==null||stuId==null){
            return new RespEntity(RespCode.PARAMS_ERROR);
        }
        //鉴别该用户是否有权转让
        Boolean authStudent = authService.authStudent(stuId, Constant.jdzcOrgCode, userId);
        if (!authStudent){
            return new RespEntity(RespCode.STUDENT_MSG_ERROR);
        }
        //管理员转让
        Integer i = jdService.changeManger(stuId, userId, wx_user);
        return new RespEntity(i > 0 ? RespCode.SUCCESS : RespCode.FAILED);
    }

    /**
     * 授权或者取消授权
     *
     * @param jsonObject
     * @return
     */
    @PutMapping("/updateAuthority")
    public RespEntity updateAuthority(@RequestBody JSONObject jsonObject,HttpServletRequest request) {
        String token = request.getHeader(Constant.HEADER_TOKEN_KEY);
        String redisUserId = redisService.getValue(token);
        if (StringUtils.isBlank(redisUserId)) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        Integer userId = Integer.parseInt(redisUserId);
        Integer id = jsonObject.getInteger("id");
        if (id == null) {
            return new RespEntity(RespCode.PARAMS_ERROR);
        }
        //根据id获取绑定记录
        Map<String, Object> map = jdService.getBindingById(id);
        if (map==null){
            return new RespEntity(RespCode.PARAMS_ERROR);
        }
        Integer is_authorization = (Integer) map.get("is_authorization");
        Integer stuId = (Integer) map.get("student");
        if (is_authorization==null||stuId==null){
            return new RespEntity(RespCode.PARAMS_ERROR);
        }
        //鉴别该用户是否有权获该学生的列表
        Boolean authStudent = authService.authStudent(stuId, Constant.jdzcOrgCode, userId);
        if (!authStudent){
            return new RespEntity(RespCode.STUDENT_MSG_ERROR);
        }
        //授权
        Integer status = (is_authorization == 1 ? 0 : 1);
        Integer i = jdService.changeAuthority(id, status);
        return new RespEntity(i > 0 ? RespCode.SUCCESS : RespCode.FAILED);
    }

    /**
     * 更新Sim卡号
     *
     * @param jsonObject
     * @return
     */
    @PutMapping("/updateSimCard")
    public RespEntity updateSimCard(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        String imei = jsonObject.getString("imei");
        String phone = jsonObject.getString("phone");
        if (StringUtils.isBlank(imei) || StringUtils.isBlank(phone)) {
            return new RespEntity(RespCode.PARAMS_ERROR);
        }
        //鉴别该设备是否属于该组织
        DeviceInfo deviceInfo = jdDeviceInfoService.getDeviceInfoByImei(imei);
        Boolean rest = authService.authDevice(deviceInfo, Constant.jdzcOrgCode);
        if (!rest) {
            return new RespEntity(RespCode.DEVICE_NOT_BELONG_TO);
        }
        int i = jdService.modifyPhoneByImei(imei, phone);
        return new RespEntity(i > 0 ? RespCode.SUCCESS : RespCode.FAILED);
    }


    /**
     * 挑选一个合适的学生id
     *
     * @param list
     * @param imei
     * @return
     */
    public Integer selectStudentId(List<Map<String, Object>> list, String imei, String deviceOrgCode) {
/*        if (list.size() == 1) {
            return (Integer) list.get(0).get("student_id");
        }*/
        List<Integer> stuIdList = new ArrayList<>();
        list.stream().forEach(e -> {
            stuIdList.add((Integer) e.get("student_id"));
        });
        List<DeviceInfo> deviceList = jdDeviceInfoService.getDeviceInfoListByStuIdList(stuIdList);
        //默认取第一个
        Integer stuId = (Integer) list.get(0).get("student_id");
        if (deviceList != null && deviceList.size() != 0) {
            for (DeviceInfo deviceInfo : deviceList) {
                if (deviceInfo.getImei().equals(imei)) {
                    stuId = deviceInfo.getStudentId();
                    return stuId;
                }
                //筛选掉已经绑定设备的
                if (stuIdList.contains(deviceInfo.getStudentId())) {
                    stuIdList.remove(deviceInfo.getStudentId());
                }
            }
        }
        //进一步筛选学校的组织和设备的组织是否匹配
        //根据学生id获取学校组织code
        if (deviceOrgCode != null) {
            if (stuIdList.size() > 0) {
                List<Map<String, Object>> schoolOrgCodeList = jdzcStudentService.getSchoolOrgCodeListByStuIdList(stuIdList);
                for (Map<String, Object> map : schoolOrgCodeList) {
                    String schoolCode = (String) map.get("org_code");
                    if (!schoolCode.contains(deviceOrgCode)) {
                        Integer stuId2 = (Integer) map.get("student_id");
                        stuIdList.remove(stuId2);
                    }
                }
            }
        }
        //到此处若还有值，则取第一个
        if (stuIdList.size() > 0) {
            return stuIdList.get(0);
        }
        return 0;
    }

    /**
     * 获取当前时间的时分秒（HHmmss）
     *
     * @return
     */
    public String getCurTime() {
        Date d = new Date();
        SimpleDateFormat sbf = new SimpleDateFormat("HH:mm:ss");
        String format = sbf.format(d);
        String[] split = format.split(":");
        String time = split[0].concat(split[1]).concat(split[2]);
        return time;
    }


    /**
     * 判断设备是否在线
     *
     * @param imei 设备imei号
     * @return 设备是否在线
     */
    public boolean deviceOnline(String imei) {
        boolean isOnline = redisService.hasKey(Constant.DEVICE_ONLINE_PREFIX + imei);
        logger.info("设备:【{}】: {}", imei, isOnline ? "在线" : "离线");
        return isOnline;
    }


}
